package cn.kgc.controller;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author YC
 */
public class Game2048 extends JFrame {
    private static final long serialVersionUID = 1L;
    private static final int SIZE = 4;
    private int[][] board = new int[SIZE][SIZE];
    private Random random = new Random();
    private boolean moved;
    private int score = 0;
    private JLabel scoreLabel;

    // 颜色映射表，对应不同数值的方块
    private static final Color[] COLORS = {
            new Color(0xcdc1b4), new Color(0xeee4da), new Color(0xede0c8),
            new Color(0xf2b179), new Color(0xf59563), new Color(0xf67c5f),
            new Color(0xf65e3b), new Color(0xedcf72), new Color(0xedcc61),
            new Color(0xedc850), new Color(0xedc53f), new Color(0xedc22e),
            new Color(0x3c3a32)
    };

    public Game2048() {
        setTitle("2048 Game");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 600);
        setLocationRelativeTo(null);
        setResizable(false);

        // 创建分数面板
        JPanel scorePanel = new JPanel();
        scorePanel.setPreferredSize(new Dimension(500, 100));
        scorePanel.setBackground(new Color(0xfaf8ef));
        scoreLabel = new JLabel("Score: 0");
        scoreLabel.setFont(new Font("Arial", Font.BOLD, 24));
        scorePanel.add(scoreLabel);
        add(scorePanel, BorderLayout.NORTH);

        // 创建游戏面板
        GamePanel gamePanel = new GamePanel();
        add(gamePanel, BorderLayout.CENTER);

        // 键盘监听
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                moved = false;
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP:
                        moveUp();
                        break;
                    case KeyEvent.VK_DOWN:
                        moveDown();
                        break;
                    case KeyEvent.VK_LEFT:
                        moveLeft();
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveRight();
                        break;
                }

                if (moved) {
                    spawnNewTile();
                    repaint();

                    if (checkGameOver()) {
                        JOptionPane.showMessageDialog(Game2048.this,
                                "Game Over! Score: " + score,
                                "Game Over",
                                JOptionPane.INFORMATION_MESSAGE);
                        resetGame();
                    }

                    if (checkWin()) {
                        JOptionPane.showMessageDialog(Game2048.this,
                                "You Win! Score: " + score,
                                "Congratulations",
                                JOptionPane.INFORMATION_MESSAGE);
                    }
                }
            }
        });

        // 初始化游戏
        resetGame();
    }

    // 重置游戏
    private void resetGame() {
        board = new int[SIZE][SIZE];
        score = 0;
        scoreLabel.setText("Score: " + score);
        spawnNewTile();
        spawnNewTile();
        repaint();
    }

    // 随机生成新方块
    private void spawnNewTile() {
        List<Point> emptyTiles = new ArrayList<>();

        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (board[i][j] == 0) {
                    emptyTiles.add(new Point(i, j));
                }
            }
        }

        if (!emptyTiles.isEmpty()) {
            Point p = emptyTiles.get(random.nextInt(emptyTiles.size()));
            // 90%概率生成2，10%概率生成4
            board[p.x][p.y] = random.nextInt(10) == 0 ? 2 : 1;
        }
    }

    // 移动逻辑 - 左移
    private void moveLeft() {
        for (int i = 0; i < SIZE; i++) {
            // 压缩空格
            int[] row = board[i];
            int[] newRow = new int[SIZE];
            int index = 0;

            for (int j = 0; j < SIZE; j++) {
                if (row[j] != 0) {
                    newRow[index++] = row[j];
                }
            }

            // 合并相同数字
            for (int j = 0; j < SIZE - 1; j++) {
                if (newRow[j] != 0 && newRow[j] == newRow[j + 1]) {
                    newRow[j]++;
                    score += (int) Math.pow(2, newRow[j]);
                    newRow[j + 1] = 0;
                    moved = true;
                }
            }

            // 再次压缩
            index = 0;
            int[] finalRow = new int[SIZE];
            for (int j = 0; j < SIZE; j++) {
                if (newRow[j] != 0) {
                    finalRow[index++] = newRow[j];
                }
            }

            // 检查是否有移动
            if (!java.util.Arrays.equals(board[i], finalRow)) {
                moved = true;
            }

            board[i] = finalRow;
        }
    }

    // 右移（通过旋转实现）
    private void moveRight() {
        rotateBoard();
        rotateBoard();
        moveLeft();
        rotateBoard();
        rotateBoard();
    }

    // 上移（通过旋转实现）
    private void moveUp() {
        rotateBoard();
        rotateBoard();
        rotateBoard();
        moveLeft();
        rotateBoard();
    }

    // 下移（通过旋转实现）
    private void moveDown() {
        rotateBoard();
        moveLeft();
        rotateBoard();
        rotateBoard();
        rotateBoard();
    }

    // 旋转棋盘
    private void rotateBoard() {
        int[][] newBoard = new int[SIZE][SIZE];

        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                newBoard[j][SIZE - 1 - i] = board[i][j];
            }
        }

        board = newBoard;
    }

    // 检查游戏是否结束
    private boolean checkGameOver() {
        // 检查是否有空位
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (board[i][j] == 0) {
                    return false;
                }
            }
        }

        // 检查是否有可合并的方块
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE - 1; j++) {
                if (board[i][j] == board[i][j + 1]) {
                    return false;
                }
            }
        }

        for (int j = 0; j < SIZE; j++) {
            for (int i = 0; i < SIZE - 1; i++) {
                if (board[i][j] == board[i + 1][j]) {
                    return false;
                }
            }
        }

        return true;
    }

    // 检查是否获胜（达到2048）
    private boolean checkWin() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (board[i][j] >= 11) { // 2^11 = 2048
                    return true;
                }
            }
        }
        return false;
    }

    // 游戏面板绘制
    class GamePanel extends JPanel {
        private static final long serialVersionUID = 1L;
        private static final int MARGIN = 16;
        private static final int CELL_SIZE = 100;

        public GamePanel() {
            setBackground(new Color(0xfaf8ef));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            // 绘制棋盘背景
            g.setColor(new Color(0xbbada0));
            g.fillRoundRect(MARGIN, MARGIN,
                    CELL_SIZE * SIZE + MARGIN * (SIZE - 1),
                    CELL_SIZE * SIZE + MARGIN * (SIZE - 1),
                    10, 10);

            // 绘制每个格子
            for (int i = 0; i < SIZE; i++) {
                for (int j = 0; j < SIZE; j++) {
                    int value = board[i][j];
                    int x = MARGIN + j * (CELL_SIZE + MARGIN);
                    int y = MARGIN + i * (CELL_SIZE + MARGIN);

                    // 绘制格子背景
                    g.setColor(COLORS[value]);
                    g.fillRoundRect(x, y, CELL_SIZE, CELL_SIZE, 5, 5);

                    // 绘制数字
                    if (value > 0) {
                        // 设置字体颜色
                        if (value <= 2) {
                            g.setColor(new Color(0x776e65));
                        } else {
                            g.setColor(new Color(0xf9f6f2));
                        }

                        // 设置字体大小
                        Font font = new Font("Arial", Font.BOLD,
                                value < 4 ? 40 :
                                        value < 6 ? 36 :
                                                value < 9 ? 32 : 24);
                        g.setFont(font);

                        // 计算文本位置
                        String text = String.valueOf((int) Math.pow(2, value));
                        FontMetrics fm = g.getFontMetrics();
                        int textX = x + (CELL_SIZE - fm.stringWidth(text)) / 2;
                        int textY = y + (CELL_SIZE + fm.getAscent()) / 2 - fm.getDescent();

                        g.drawString(text, textX, textY);
                    }
                }
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(
                    CELL_SIZE * SIZE + MARGIN * (SIZE + 1),
                    CELL_SIZE * SIZE + MARGIN * (SIZE + 1)
            );
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new Game2048().setVisible(true);
        });
    }
}
